// internal/apps/auth/services/user_service.go
package services

import (
	"errors"
	"math"
	"star-go-app/internal/apps/auth/models"
	"star-go-app/internal/apps/auth/models/manager"
	"star-go-app/internal/apps/auth/repositories"
	"star-go-app/internal/apps/auth/serializers"
)

// UserService 用户服务
type UserService struct {
	userRepo   repositories.UserRepository
	userDomain *manager.UserDomain
}

// NewUserService 创建用户服务
func NewUserService(userRepo repositories.UserRepository) *UserService {
	return &UserService{
		userRepo:   userRepo,
		userDomain: manager.NewUserDomain(),
	}
}

// CreateUser 创建用户
func (s *UserService) CreateUser(req *serializers.CreateUserRequest) (*serializers.UserResponse, error) {
	// 验证用户数据
	if err := s.userDomain.ValidateUserData(req.Username, req.Email); err != nil {
		return nil, err
	}

	// 检查用户名是否已存在
	if _, err := s.userRepo.GetByUsername(req.Username); err == nil {
		return nil, errors.New("用户名已存在")
	}

	// 检查邮箱是否已存在
	if _, err := s.userRepo.GetByEmail(req.Email); err == nil {
		return nil, errors.New("邮箱已存在")
	}

	// 创建用户实体
	user := &models.User{
		Username: req.Username,
		Email:    req.Email,
		RoleID:   req.RoleID,
	}

	// 设置密码
	if err := s.userDomain.SetPassword(user, req.Password); err != nil {
		return nil, err
	}

	// 保存用户
	if err := s.userRepo.Create(user); err != nil {
		return nil, err
	}

	// 获取完整用户信息（包括角色）
	userWithRole, err := s.userRepo.GetByID(user.ID)
	if err != nil {
		return nil, err
	}

	return s.toUserResponse(userWithRole), nil
}

// GetUserByID 根据ID获取用户
func (s *UserService) GetUserByID(id uint) (*serializers.UserDetailResponse, error) {
	user, err := s.userRepo.GetByID(uint64(id))
	if err != nil {
		return nil, err
	}

	return s.toUserDetailResponse(user), nil
}

// GetUserList 获取用户列表
func (s *UserService) GetUserList(req *serializers.UserListRequest) (*serializers.UserListResponse, error) {
	// 计算offset
	offset := (req.Page - 1) * req.PageSize

	// 获取用户列表（暂时使用简单的分页，后续可以扩展过滤功能）
	users, total, err := s.userRepo.GetList(offset, req.PageSize)
	if err != nil {
		return nil, err
	}

	// 转换为响应格式
	userList := make([]serializers.UserResponse, len(users))
	for i, user := range users {
		userList[i] = *s.toUserResponse(user)
	}

	// 计算总页数
	totalPages := int(math.Ceil(float64(total) / float64(req.PageSize)))

	return &serializers.UserListResponse{
		List:       userList,
		Total:      total,
		Page:       req.Page,
		PageSize:   req.PageSize,
		TotalPages: totalPages,
	}, nil
}

// UpdateUser 部分更新用户
func (s *UserService) UpdateUser(id uint, req *serializers.UpdateUserRequest) (*serializers.UserResponse, error) {
	uid := uint64(id)

	// 检查用户是否存在
	if !s.userRepo.Exists(uid) {
		return nil, errors.New("用户不存在")
	}

	// 构建更新字段
	updateFields := make(map[string]interface{})

	if req.Username != nil {
		// 检查用户名是否已存在（排除当前用户）
		if existingUser, err := s.userRepo.GetByUsername(*req.Username); err == nil && existingUser.ID != uid {
			return nil, errors.New("用户名已存在")
		}
		updateFields["username"] = *req.Username
	}

	if req.Email != nil {
		// 检查邮箱是否已存在（排除当前用户）
		if existingUser, err := s.userRepo.GetByEmail(*req.Email); err == nil && existingUser.ID != uid {
			return nil, errors.New("邮箱已存在")
		}
		updateFields["email"] = *req.Email
	}

	if req.RoleID != nil {
		updateFields["role_id"] = *req.RoleID
	}

	// 执行更新
	if err := s.userRepo.UpdateFields(uid, updateFields); err != nil {
		return nil, err
	}

	// 获取更新后的用户信息
	updatedUser, err := s.userRepo.GetByID(uid)
	if err != nil {
		return nil, err
	}

	return s.toUserResponse(updatedUser), nil
}

// UpdateUserWhole 完整更新用户
func (s *UserService) UpdateUserWhole(id uint, req *serializers.UpdateUserWholeRequest) (*serializers.UserResponse, error) {
	uid := uint64(id)

	// 检查用户是否存在
	user, err := s.userRepo.GetByID(uid)
	if err != nil {
		return nil, err
	}

	// 验证用户数据
	if err := s.userDomain.ValidateUserData(req.Username, req.Email); err != nil {
		return nil, err
	}

	// 检查用户名是否已存在（排除当前用户）
	if existingUser, err := s.userRepo.GetByUsername(req.Username); err == nil && existingUser.ID != uid {
		return nil, errors.New("用户名已存在")
	}

	// 检查邮箱是否已存在（排除当前用户）
	if existingUser, err := s.userRepo.GetByEmail(req.Email); err == nil && existingUser.ID != uid {
		return nil, errors.New("邮箱已存在")
	}

	// 更新用户信息
	user.Username = req.Username
	user.Email = req.Email
	user.RoleID = req.RoleID

	// 保存更新
	if err := s.userRepo.Update(user); err != nil {
		return nil, err
	}

	// 获取更新后的用户信息
	updatedUser, err := s.userRepo.GetByID(uid)
	if err != nil {
		return nil, err
	}

	return s.toUserResponse(updatedUser), nil
}

// DeleteUser 软删除用户
func (s *UserService) DeleteUser(id uint) error {
	return s.userRepo.Delete(uint64(id))
}

// DeleteUserPermanently 永久删除用户
func (s *UserService) DeleteUserPermanently(id uint) error {
	return s.userRepo.DeletePermanently(uint64(id))
}

// ChangePassword 修改密码
func (s *UserService) ChangePassword(id uint, req *serializers.ChangePasswordRequest) error {
	user, err := s.userRepo.GetByID(uint64(id))
	if err != nil {
		return err
	}

	// 验证旧密码
	if !s.userDomain.CheckPassword(user, req.OldPassword) {
		return errors.New("旧密码错误")
	}

	// 设置新密码
	if err := s.userDomain.SetPassword(user, req.NewPassword); err != nil {
		return err
	}

	// 保存更新
	return s.userRepo.Update(user)
}

// toUserResponse 转换为用户响应格式
func (s *UserService) toUserResponse(user *models.User) *serializers.UserResponse {
	response := &serializers.UserResponse{
		ID:        uint(user.ID),
		Username:  user.Username,
		Email:     user.Email,
		RoleID:    user.RoleID,
		CreatedAt: user.CreatedAt,
		UpdatedAt: user.UpdatedAt,
	}

	if user.Role != nil {
		response.RoleName = user.Role.Name
	}

	return response
}

// toUserDetailResponse 转换为用户详情响应格式
func (s *UserService) toUserDetailResponse(user *models.User) *serializers.UserDetailResponse {
	response := &serializers.UserDetailResponse{
		ID:        uint(user.ID),
		Username:  user.Username,
		Email:     user.Email,
		RoleID:    user.RoleID,
		CreatedAt: user.CreatedAt,
		UpdatedAt: user.UpdatedAt,
	}

	// 角色信息
	if user.Role != nil {
		response.Role = serializers.RoleResponse{
			ID:          uint(user.Role.ID),
			Name:        user.Role.Name,
			Description: user.Role.Description,
		}

		// 权限信息
		permissions := s.userDomain.GetUserPermissions(user)
		response.Permissions = make([]serializers.PermissionResponse, len(permissions))
		for i, perm := range permissions {
			response.Permissions[i] = serializers.PermissionResponse{
				Resource: perm.Resource,
				Action:   perm.Action,
			}
		}
	}

	return response
}
